package com.wms.execcmd;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Date;

import org.apache.log4j.Logger;

public class ShellHelper {
	private final static String PARAMS_DELIMITER = ";";
	private String stdout = "";
	private String stderr = "";
	private static String workingDir = null;
	private static Logger logger = Logger.getLogger(ShellHelper.class);

	public ShellHelper() {
		
		workingDir = System.getenv("CI_WORKDIR");
		if(null == workingDir || ""== workingDir)
		{
			workingDir=File.separator+"tmp";
		}
	}

	public int executeBatch(String scripts, String[] env, long timeout)
			throws IOException {
		File temp = null;
		BufferedWriter writer = null;
		int retValue = -1;
		try {
			temp = File.createTempFile("tmp"+ System.currentTimeMillis(), ".sh", new File(workingDir));			writer = new BufferedWriter(new FileWriter(temp));
			writer.write("#!/bin/sh");
			writer.write("\n");
			writer.write(scripts.replace('\r', ' '));
			writer.flush();
			writer.close();
			writer = null;
			retValue = this
					.execute(new String[] { "sh", temp.getAbsolutePath() },
							env, timeout);
		}
		finally {
			if (writer != null) {
				try {
					writer.close();
				}
				catch (Throwable th) {
					// Ignore the error
				}
			}

			if (temp != null) {
				temp.delete();
			}
		}

		return retValue;
	}

	public int execute(String[] cmdArray, String[] envp, long timeout)
			throws IOException {
		// Command wrapper for command execution
		CommandWrapper cmdWrapper = new CommandWrapper(logger);

		// Set reader to read stdout
		DefaultOutputReader stdoutReader = new DefaultOutputReader(logger);
		cmdWrapper.setStdoutReader(stdoutReader);

		// Set reader to read stderr
		DefaultOutputReader stderrReader = new DefaultOutputReader(logger);
		cmdWrapper.setStderrReader(stderrReader);
		// Execute the given command
		int retValue = cmdWrapper.exec(cmdArray, envp, timeout);
		if (logger.isDebugEnabled()) {
			logger.debug("stdout: " + stdoutReader.getBuffer());
			logger.debug("stderr: " + stderrReader.getBuffer());
		}

		this.stdout = stdoutReader.getBuffer().toString();
		// Set stderr for later use
		this.stderr = stderrReader.getBuffer().toString();
		System.out.println("stderr="+stderr);
		return retValue;
	}

	/**
	 * Split a given command line with argument to an array, for example "echo
	 * Hello" to {"echo", "Hello"}
	 *
	 * @param cmd
	 *            specifies the command line to split
	 * @return array of string
	 */
	public static String[] splitCmd(String cmd) {
		List<String> cmdList = new ArrayList<String>();
		int len = cmd.length();
		int head = 0;
		int quotationCount = 0;
		int index = 0;
		while (index < len) {
			char ch = cmd.charAt(index);
			if (ch == '"') {
				quotationCount++;
				index++;
				continue;
			}
			else if (ch == ' ') {
				if (quotationCount % 2 == 0) {
					cmdList.add(cmd.substring(head, index));
					index++;

					// Eat whitespace
					while (index < len) {
						if (cmd.charAt(index) == ' ') {
							index++;
						}
						else {
							break;
						}
					}
					head = index;
					continue;
				}
			}
			index++;
		}

		if (head < index) {
			cmdList.add(cmd.substring(head, index));
		}
		return cmdList.toArray(new String[cmdList.size()]);
	}

	public static Map<String, String> convertMap(Map<String, Object> input) {
		Map<String, String> result = new HashMap<String, String>();
		if (input == null) {
			return null;
		}
		for (Map.Entry<String, Object> entry : input.entrySet()) {
			StringBuffer combinedValue = new StringBuffer();

			String name = entry.getKey();
			Object values = entry.getValue();

			if (values != null) {
				if (values instanceof String[]) {
					String[] tmp = (String[]) values;
					for (int k = 0; k < tmp.length; k++) {
						if (k != 0) {
							combinedValue.append(PARAMS_DELIMITER);
						}
						combinedValue.append(tmp[k]);
					}
					result.put(name, combinedValue.toString());
				}
				else {
					result.put(name, values.toString());
				}
			}
		}
		return result;
	}

	/**
	 * Convert map the environment parameters required by command-line execution
	 *
	 * @param params
	 * @return
	 */
	public static String[] mapToEnvParams(Map<String, String> params) {
		if (params == null) {
			return null;
		}

		String[] envp = new String[params.size()];
		int index = 0;

		for (Map.Entry<String, String> entry : params.entrySet()) {
			String name = entry.getKey();
			String value = entry.getValue();
			envp[index] = name + "=" + value;

			if (logger.isDebugEnabled()) {
				logger.debug(envp[index]);
			}
			index++;
		}
		return envp;
	}


	public String getStdout() {
		return stdout;
	}

	public String getStderr() {
		return stderr;
	}

	public void setStdout(String stdout) {
		this.stdout = stdout;
	}

	public void setStderr(String stderr) {
		this.stderr = stderr;
	}
}
